home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
forms
/
FORMS
/
fselect.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
373 lines
/*
* fdesign.c
*
* This file belongs to the goodies of the Forms Library.
*
* It contains the file selector.
*
* Written by: Mark Overmars and Trevor Paquette
*
* Version 2.2 b
* Date: Jun 18, 1993
*/
#include <malloc.h>
#include <unistd.h>
#include <strings.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "forms.h"
/* the following is strictly for compilation on an Ultrix
* with gcc
*/
#if defined(__vax__) || defined(__STRICT_ANSI__)
extern int scandir(const char *, struct dirent **[],
int (*select)(struct dirent *),
int (*howsort)(struct dirent **, struct dirent **));
extern int alphasort(struct dirent **, struct dirent **);
#endif
static FL_FORM *fsform;
static FL_OBJECT *messageobj, *selectionobj, *readyobj, *cancelobj,
*selectobj, *directoryobj, *patternobj;
static char fl_directory[256]; /* Current directory */
static char fl_pattern[256]; /* Current pattern */
static char fl_filename[256]; /* Current selected file name */
/*------------------- Pattern matching --------------------------*/
/* Adapted from Rich Salz. */
static int do_matching(char *, char *);
static int match_star(char *s, char *p)
{
int result;
while( (result = do_matching(s, p)) == FALSE) /* gobble up * match */
if(*++s == NULL) return -1;
return result;
}
static int do_matching(char *s, char *p)
/* match string "s" to pattern "p" */
{
int last, matched, reverse;
for ( ; *p; s++, p++)
{
if(*s == NULL) return (*p == '*' && *++p == NULL ? TRUE : -1);
switch(*p)
{ /* parse pattern */
case '\\': /* Literal match with following character. */
if(*s != *++p) return FALSE;
continue;
default : /*literal match*/
if(*s != *p) return FALSE;
continue;
case '?' : /* Match anything. */
continue;
case '*' : /* Trailing star matches everything. */
return (*++p ? match_star(s, p) : TRUE);
case '[': /* [!....] means inverse character class. */
if (reverse = p[1] == '!') p++;
for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
/* This next line requires a good C compiler. */
/* range? (in bounds) (equal) */
if((*p == '-') ? (*s <= *++p && *s >= last ) : (*s == *p))
matched = TRUE;
if(matched == reverse) return FALSE;
continue;
}
}
return *s == NULL;
}
static int wildmat(char *s, char *p)
{
if (*p == NULL && *s != '.') return TRUE;
else if (*p == NULL) return FALSE;
else if ( (*p == '?' || *p == '*' ) && *s == '.') return FALSE;
else return do_matching(s, p) == TRUE;
}
static int match_pattern(struct dirent *file)
{
char tmpstr[256];
struct stat fstat;
strcpy(tmpstr,fl_directory);
if (strlen(fl_directory)==0 || fl_directory[strlen(fl_directory)-1]!='/')
strcat(tmpstr,"/");
strcat(tmpstr,file->d_name);
stat(tmpstr,&fstat);
if (fstat.st_mode & S_IFDIR) return TRUE;
return(wildmat(file -> d_name, fl_pattern));
}
/*------------------- Routine to correct directory ------------*/
static void set_dirpath()
/* Corrects the directory path. */
{
char tmpstr[256];
int i,j,k;
if (fl_directory[0] == NULL)
strcpy(tmpstr,"/");
else if (fl_directory[0] != '/')
{
getcwd(tmpstr,256);
strcat(tmpstr,"/");
strcat(tmpstr,fl_directory);
}
else
strcpy(tmpstr,fl_directory);
for (i=0; i < strlen(tmpstr); i++)
{
if (tmpstr[i] == '/' && tmpstr[i+1] == '.' &&
(tmpstr[i+2] == '/' || tmpstr[i+2] == NULL))
{
for (j=i+2; tmpstr[j-1] != NULL; j++) tmpstr[j-2] = tmpstr[j];
i--;
}
else if (tmpstr[i] == '/' && tmpstr[i+1] == '.' && tmpstr[i+2] == '.' &&
(tmpstr[i+3] == '/' || tmpstr[i+3] == NULL))
{
if (i==0)
{
for (j=i+3; tmpstr[j-1] != NULL; j++) tmpstr[j-3] = tmpstr[j];
i = -1;
}
else
{
for (k=i-1; tmpstr[k] != '/'; k--) ;
for (j=i+3; tmpstr[j-1] != NULL; j++) tmpstr[j+k-i-3] = tmpstr[j];
i = k-1;
}
}
}
if (tmpstr[0] == NULL) strcpy(tmpstr,"/");
strcpy(fl_directory,tmpstr);
fl_set_object_label(directoryobj,tmpstr);
}
/*------------------- Routine to fill in the browser ------------*/
static void fillin_choices()
/* Fills in the choices in the library based on the current directory and
pattern. */
{
struct dirent **namelist;
struct stat fstat;
int i,fnumb;
char tmpstr[256];
/* Read the directory contents */
fnumb = scandir(fl_directory, &namelist, match_pattern, alphasort);
if (fnumb < 0)
{
fl_show_message("Cannot open:", fl_directory, "for reading.");
fl_clear_browser(selectobj);
return;
}
/* Fill in the browser */
fl_freeze_form(fsform);
fl_clear_browser(selectobj);
for (i=0; i<fnumb; i++)
{
strcpy(tmpstr,fl_directory);
if (strlen(fl_directory)==0 || fl_directory[strlen(fl_directory)-1]!='/')
strcat(tmpstr,"/");
strcat(tmpstr,namelist[i]->d_name);
stat(tmpstr,&fstat);
if (fstat.st_mode & S_IFDIR)
sprintf(tmpstr,"D %s",namelist[i]->d_name);
else
sprintf(tmpstr," %s",namelist[i]->d_name);
fl_add_browser_line(selectobj,tmpstr);
free(namelist[i]);
}
fl_unfreeze_form(fsform);
free(namelist);
}
/*----------------------- The Callback Routines -----------------*/
static int lastline = 0;
static long lastsec = 0;
static long lastusec = 0;
static int select_cb(FL_OBJECT *obj, long arg)
/* user selected something in the selector */
{
char seltext[256];
int dir, i;
struct timeval tp;
struct timezone tzp;
strcpy(seltext,fl_get_browser_line(obj,fl_get_browser(obj)));
dir = seltext[0] == 'D';
for (i= 2; i<=strlen(seltext); i++) seltext[i-2] = seltext[i];
if (dir)
{
if (strlen(fl_directory)== 0 || fl_directory[strlen(fl_directory)-1] != '/')
strcat(fl_directory,"/");
strcat(fl_directory,seltext);
set_dirpath();
fillin_choices();
return 0;
}
else
{
fl_set_input(selectionobj,seltext);
strcpy(fl_filename,seltext);
gettimeofday(&tp,&tzp);
if (lastline == fl_get_browser(obj))
{
if (1000000*(tp.tv_sec - lastsec) + (tp.tv_usec - lastusec) < 400000)
return 1;
}
lastline = fl_get_browser(obj);
lastsec = tp.tv_sec; lastusec = tp.tv_usec;
return 0;
}
}
static void directory_cb(FL_OBJECT *obj, long arg)
/* User wants to change the directory */
{
strcpy(fl_directory,fl_show_input("Enter new directory:",fl_directory));
set_dirpath();
fillin_choices();
}
static void pattern_cb(FL_OBJECT *obj, long arg)
/* User wants to change the pattern */
{
strcpy(fl_pattern,fl_show_input("Enter new pattern:",fl_pattern));
fl_set_object_label(patternobj,fl_pattern);
fillin_choices();
}
static void filename_cb(FL_OBJECT *obj, long arg)
/* User changed the file name. Nothing needs to be done */
{
}
/*------------------- The form definition -----------------------*/
static void create_fs_form(void)
{
FL_OBJECT *obj;
fsform = fl_bgn_form(FL_NO_BOX,530.0,460.0);
obj = fl_add_box(FL_UP_BOX,0.0,0.0,530.0,460.0,"");
fl_set_object_color(obj,12,47);
messageobj = obj = fl_add_box(FL_BORDER_BOX,20.0,410.0,490.0,30.0,"A message");
fl_set_object_color(obj,53,47);
selectionobj = obj = fl_add_input(FL_NORMAL_INPUT,290.0,270.0,220.0,30.0,"file name");
fl_set_object_boxtype(obj,FL_SHADOW_BOX);
fl_set_object_color(obj,52,9);
fl_set_object_align(obj,FL_ALIGN_TOP);
fl_set_object_lstyle(obj,FL_BOLD_STYLE);
fl_set_call_back(obj,filename_cb,0);
readyobj = obj = fl_add_button(FL_RETURN_BUTTON,380.0,120.0,130.0,40.0,"Ready");
cancelobj = obj = fl_add_button(FL_NORMAL_BUTTON,380.0,50.0,130.0,40.0,"Cancel");
obj = fl_add_box(FL_SHADOW_BOX,20.0,20.0,240.0,300.0,"");
selectobj = obj = fl_add_browser(FL_HOLD_BROWSER,20.0,20.0,240.0,300.0,"");
fl_set_object_boxtype(obj,FL_BORDER_BOX);
fl_set_object_color(obj,53,9);
directoryobj = obj = fl_add_text(FL_NORMAL_TEXT,90.0,370.0,420.0,30.0,"Text");
fl_set_object_boxtype(obj,FL_BORDER_BOX);
fl_set_object_color(obj,52,47);
fl_set_object_lsize(obj,10.000000);
obj = fl_add_text(FL_NORMAL_TEXT,10.0,370.0,80.0,30.0,"directory");
fl_set_object_align(obj,FL_ALIGN_RIGHT);
fl_set_object_lstyle(obj,FL_BOLD_STYLE);
patternobj = obj = fl_add_text(FL_NORMAL_TEXT,90.0,340.0,420.0,30.0,"Text");
fl_set_object_boxtype(obj,FL_BORDER_BOX);
fl_set_object_color(obj,52,47);
fl_set_object_lsize(obj,10.000000);
obj = fl_add_text(FL_NORMAL_TEXT,10.0,340.0,80.0,30.0,"pattern");
fl_set_object_align(obj,FL_ALIGN_RIGHT);
fl_set_object_lstyle(obj,FL_BOLD_STYLE);
obj = fl_add_button(FL_HIDDEN_BUTTON,90.0,370.0,420.0,30.0,"");
fl_set_object_lsize(obj,FL_SMALL_FONT);
fl_set_call_back(obj,directory_cb,0);
obj = fl_add_button(FL_HIDDEN_BUTTON,90.0,340.0,420.0,30.0,"");
fl_set_call_back(obj,pattern_cb,0);
fl_end_form();
}
/*----------------------- The Main Routine ----------------------*/
static int created = 0; /* Whether form is created. */
static char combined[512]; /* Used to contain the combined file name. */
char *fl_show_file_selector(char message[],char dir[],char pat[],char fname[])
/* Displays the file selector. Returns whether Ready was pressed. */
{
FL_OBJECT *obj;
/* Create form if required. */
if (!created)
{
strcpy(fl_directory,".");
strcpy(fl_pattern,"*");
fl_filename[0] = NULL;
create_fs_form();
created = 1;
}
/* Fill in the fields. */
fl_set_object_label(messageobj,message);
if (dir != NULL && dir[0] != '\0') strcpy(fl_directory,dir);
if (pat != NULL && pat[0] != '\0') strcpy(fl_pattern,pat);
if (fname != NULL && fname[0] != '\0') strcpy(fl_filename,fname);
set_dirpath();
fl_set_object_label(patternobj,fl_pattern);
fl_set_input(selectionobj,fl_filename);
fillin_choices();
/* Show the form. */
fl_set_browser_fontstyle(selectobj,FL_FIXED_STYLE);
fl_set_object_focus(fsform,selectionobj);
fl_deactivate_all_forms();
fl_show_form(fsform,FL_PLACE_CENTER,FALSE,NULL);
do {
obj = fl_do_only_forms();
if (obj == selectobj)
if (select_cb(selectobj,0)) break;
} while (obj != readyobj && obj != cancelobj);
fl_hide_form(fsform);
fl_activate_all_forms();
/* Return value */
if (obj == cancelobj) return NULL;
strcpy(fl_filename,fl_get_input(selectionobj));
strcpy(combined,fl_directory);
if (strlen(fl_directory) == 0 || fl_directory[strlen(fl_directory)-1] != '/')
strcat(combined,"/");
strcat(combined,fl_filename);
return combined;
}
char *fl_get_directory()
/* returns a pointer to the directory */
{ return fl_directory; }
char *fl_get_pattern()
/* returns a pointer to the pattern */
{ return fl_pattern; }
char *fl_get_filename()
/* returns a pointer to the filename */
{ return fl_filename; }